import requests
import re
import xlwt
import xlrd
import numpy as np
import matplotlib.pyplot as plt

headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 4.1.2; Nexus 7 Build/JZ054K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19',
        'Accept-Encoding': 'gzip, deflate',
        'Referer': 'http://cnnvd.org.cn/web/vulnerability/queryLds.tag'
    }

class information:   #用类实现结构体
    def __init__(self):
        self.Name = ''     # 名称
        self.Release_time = ''     # 时间
        self.Hazard_rating = ''     # 危险程度
        self.patch = 0    #是否解决，有无补丁

Data_information = []  #实现结构体数组

def crawler(month,number):
    print(1)
    if number < 10:
        number_str = "00" + str(number)
    elif number <100:
        number_str = "0" + str(number)
    else:
        number_str = str(number)
    try:
        response = requests.get("http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-20190"+str(month)+"-"+number_str, headers = headers)
        Name = re.findall(r'<h2>(.*?)</h2>',response.text,re.S)
        Release_time = re.findall(r'startdateXq=(.*?)" >',response.text,re.S)
        Hazard_rating = re.findall('cvHazardRating\',\'(.*?)\'',response.text,re.S)
        patch = re.findall(r'<p style="text-indent:2em;border-bottom-width: 80px;padding-bottom: 80px;">(.*?)</p>',response.text,re.S)
        Data_information.append(information())
        Data_information[-1].Name = Name[0]
        Data_information[-1].Release_time = Release_time[0]
        if Hazard_rating == ['']:
            Data_information[-1].Hazard_rating = '危险未知'
        else:
            Data_information[-1].Hazard_rating = Hazard_rating[0]
        if patch == []:
            Data_information[-1].patch = 1
    except:
        print("编号" + str(month) + '月' + number_str + "没有")

# crawler(2,4)
# print(Data_information[0].Name)
# print(Data_information[0].Release_time)
# print(Data_information[0].Hazard_rating)
# print(Data_information[0].patch)

def wt_excel():
    for month in range(1,9):        #9
        for number in range(1,5473):  #5473
            crawler(month,number)
    workbook = xlwt.Workbook(encoding = 'utf-8')
    worksheet = workbook.add_sheet('My Worksheet')
    worksheet.write(0,0, 'Name')
    worksheet.write(0,1, 'Release_time')
    worksheet.write(0,2, 'Hazard_rating')
    worksheet.write(0,3, 'patch')
    for i in range(len(Data_information)):
        worksheet.write(i + 1, 0, Data_information[i].Name)
        worksheet.write(i + 1, 1, Data_information[i].Release_time)
        worksheet.write(i + 1, 2, Data_information[i].Hazard_rating)
        worksheet.write(i + 1, 3, Data_information[i].patch)
    workbook.save('demo.xls')
# wt_excel()

#数据处理
data = xlrd.open_workbook("demo.xls")
table = data.sheet_by_name('My Worksheet')
times = table.col_values(1,1)
hazard = table.col_values(2,1)
patch = table.col_values(3,1)

week_0day = [0]*32
haza_low = [0]*8
haza_middle = [0]*8
haza_high = [0]*8
haza_supper = [0]*8
haza_none = [0]*8
pat = [0]*8

for month in range(1,9):
    j = 0
    k = 0
    for i in range(len(times)):
        if times[i] >= '2019-0'+str(month)+'-01' and times[i] <= '2019-0'+str(month)+'-31':
            if hazard[i] == '低危':
                haza_low[month-1] += 1
            elif hazard[i] == '中危':
                haza_middle[month-1] += 1
            elif hazard[i] == '高危':
                haza_high[month-1] += 1
            elif hazard[i] == '超危':
                haza_supper[month-1] += 1
            else:
                haza_none[month-1] += 1
            j += 1
            if patch[i] == 1:
                k += 1
    pat[month-1] = k/j

for month in range(1,9):
    for time in times:
        if time >= '2019-0'+str(month)+'-01' and time <= '2019-0'+str(month)+'-07':
            week_0day[month * 4 - 4] += 1
        elif time >= '2019-0'+str(month)+'-08' and time <= '2019-0'+str(month)+'-14':
            week_0day[month * 4 - 3] += 1
        elif time >= '2019-0'+str(month)+'-15' and time <= '2019-0'+str(month)+'-21':
            week_0day[month * 4 - 2] += 1
        elif time >= '2019-0'+str(month)+'-22' and time <= '2019-0'+str(month)+ '-31':
            week_0day[month * 4 - 1] += 1

print(week_0day)
#线性回归预测
def fit(x,y):
    if len(x) != len(y):
        return
    numerator = 0.0
    denominator = 0.0
    x_mean = np.mean(x) #求均值
    y_mean = np.mean(y)
    for i in range(len(x)):
        numerator += (x[i]-x_mean)*(y[i]-y_mean)
        denominator += np.square((x[i]-x_mean)) #计算方差
    b0 = numerator/denominator
    b1 = y_mean - b0*x_mean
    return b0,b1

def predit(x,b0,b1):
    return b0*x + b1

#预测
week_0day_x = list(range(1,33))
b0, b1 = fit(week_0day_x,week_0day)
for week in range(33,37):
    week_0day.append(predit(week,b0,b1))

def forecast(old_list):
    x_list = list(range(1,9))
    b0, b1 = fit(x_list,old_list)
    old_list.append(predit(9,b0,b1))

forecast(haza_low)
forecast(haza_middle)
forecast(haza_high)
forecast(haza_supper)
forecast(haza_none)
forecast(pat)

pie = [haza_low[-1],haza_middle[-1],haza_high[-1],haza_supper[-1],haza_none[-1]]
pie_labels = ['低危','中危','高危','超危','未知危险']

plt.figure(figsize = (18, 9))
plt.rcParams['font.sans-serif'] = 'SimHei' #设置rc参数实现显示中文
plt_a = plt.subplot(221)
plt_b = plt.subplot(222)
plt_c = plt.subplot(223)

plt_a.plot(list(range(1,37)), week_0day)
plt_b.plot(list(range(1,10)),pat)
plt_c.pie(x=pie,labels=pie_labels)
plt.show()